//---------------------------------------------------------------------------------
// Copyright (c) 2008 David Vescovi.  All rights reserved.
//
// Example managed I2C interface to DS1307 Real Time Clock (RTC)
//
//---------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using OpenNETCF;
using OpenNETCF.WindowsCE;
using Gumstix;

namespace I2C_RTC
{
    public partial class Form1 : Form
    {
        /// <summary>
        /// I2C object instance
        /// </summary>
        I2C i2c;

        /// <summary>
        /// Slave address of I2C RTC
        /// </summary>
        private const Byte I2CSlaveAddress = 0x68;

        public Form1()
        {
            InitializeComponent();
            i2c = new I2C();
        }

        #region BCD/Binary converters
        /// <summary>
        /// Convert to two digit packed BCD
        /// </summary>
        /// <param name="data">binary integer to convert</param>
        /// <returns>Packed BCD byte</returns>
        private Byte toBCD(Int32 data)
        {
            int a = data;
            int b = 0;
            if (data >= 10)
            { // Make sure there are two digits
                a = data % 10;
                b = (data / 10) % 10;
            }
            return (Byte)((b << 4) | a);
        }

        /// <summary>
        /// Convert two digit packe BCD byte to binary integer
        /// </summary>
        /// <param name="data">Packed BCD byte</param>
        /// <returns>Converted integer</returns>
        private Int32 toBinary(Byte data)
        {
            return ((Int32)((data >> 4) * 10) + (Int32)(0x0F & data));
        }

        #endregion

        /// <summary>
        /// Sets or Gets the time registers in the DS1307 RTC
        /// </summary>
        public DateTime rtcTime
        {
            set
            {
                UInt64 rtcTime = 0;
                int year;
                DateTime timeNow = value;
                year = timeNow.Year;
                if (year >= 2000)
                {
                    year -= 2000;
                }
                else
                {
                    year -= 1900;
                }

                rtcTime = (UInt64)toBCD(timeNow.Second) << 8 | (UInt64)toBCD(timeNow.Minute) << 16 | (UInt64)toBCD(timeNow.Hour) << 24 | ((UInt64)timeNow.DayOfWeek + 1) << 32 |
                    (UInt64)toBCD(timeNow.Day) << 40 | (UInt64)toBCD(timeNow.Month) << 48 | (UInt64)toBCD(year) << 56;

                i2c.Write(I2CSlaveAddress, rtcTime);
            }
            get
            {
                UInt64 rtcTime = 0;
                i2c.Write(I2CSlaveAddress, (Byte)0x00);
                i2c.Read(I2CSlaveAddress, ref rtcTime);
                DateTime timeNow = new DateTime(toBinary((Byte)(rtcTime >> 48)) + 2000,toBinary((Byte)(rtcTime >> 40)),toBinary((Byte)(rtcTime >> 32)),
                    toBinary((Byte)(rtcTime >> 16)),toBinary((Byte)(rtcTime >> 8)),toBinary((Byte)(rtcTime)));
                return timeNow;
            }
        }

        private void btnGetRTC_Click(object sender, EventArgs e)
        {
            DateTime now = rtcTime;
            lblRTCTime.Text = now.ToString() + " UTC";
        }

        private void btnSetRTC_Click(object sender, EventArgs e)
        {
            rtcTime = DateTime.UtcNow;
        }

        private void btnSetSystem_Click(object sender, EventArgs e)
        {
            DateTimeHelper.SystemTime = rtcTime;
        }
    }
}